import type { AxiosInstance } from 'axios'
import axios from 'axios'
import { ElNotification } from 'element-plus'
import { GET_REFRESH_TOKEN, GET_TOKEN, HAS_EXPIRED } from '@/utils/token'
import { ApiCodeEnums, HeaderEnums } from './enums'

import useUserStore from '@/store/modules/user'
import useRefreshStore from '@/store/modules/refresh.ts'
import { refreshLogin } from '@/api/acl/user'

//创建axios实例
const request: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 5000,
})
/* 被挂起的请求数组 */
let refreshSubscribers: any[] = []

/* push所有请求到数组中 */
const subscribeTokenRefresh = (cb: any): void => {
  refreshSubscribers.push(cb)
}

/* 刷新请求（refreshSubscribers数组中的请求得到新的token之后会自执行，用新的token去请求数据） */
const onRefreshed = (token: string): void => {
  refreshSubscribers.map((cb) => cb(token))
}
//请求拦截器
request.interceptors.request.use(
  (config) => {
    config.headers['Authorization'] = HeaderEnums.BASIC_AUTH_ENUM
    config.headers['client-type'] = 'WEB'
    if (GET_TOKEN()) {
      if (HAS_EXPIRED()) {
        const refreshStore = useRefreshStore()
        if (!refreshStore.refreshState.refresh) {
          refreshStore.refreshState.refresh = true
          const userStore = useUserStore()
          refreshLogin({ refreshToken: GET_REFRESH_TOKEN() })
            .then(async (result) => {
              if (result.code == 200) {
                await userStore.cacheAccessToken(result.data)
                onRefreshed(GET_TOKEN())
                /* 执行onRefreshed函数后清空数组中保存的请求 */
                refreshSubscribers = []
              } else {
                userStore.logout()
              }
            })
            .catch(async () => {
              userStore.logout()
            })
            .finally(() => (refreshStore.refreshState.refresh = false))
        } else {
          config.headers[HeaderEnums.BEARER_TOKEN_ENUM] = GET_TOKEN()
          return config
        }
      } else {
        config.headers[HeaderEnums.BEARER_TOKEN_ENUM] = GET_TOKEN()
        return config
      }
      /* 把请求(token)=>{....}都push到一个数组中 */
      return new Promise((resolve) => {
        /* (token) => {...}这个函数就是回调函数 */
        subscribeTokenRefresh((token: string) => {
          config.headers[HeaderEnums.BEARER_TOKEN_ENUM] = token
          /* 将请求挂起 */
          resolve(config)
        })
      })
    } else {
      return config
    }
  },
  (error) => {
    return Promise.reject(error)
  },
)
//响应拦截器
request.interceptors.response.use(
  (response) => {
    const result = response.data
    // 处理刷新token失败的逻辑
    if (result.code === ApiCodeEnums.REFRESH_ERROR) {
      ElNotification({
        message: '凭证超时,请重新登录',
        type: 'error',
      })
      const userStore = useUserStore()
      userStore.logout()
      return response.data
    }
    if (result.code !== ApiCodeEnums.API_OK) {
      ElNotification({
        message: result.msg,
        type: 'error',
      })
    }
    return response.data
  },
  (error) => {
    ElNotification({
      title: '请求失败',
      message: '请联系管理员',
      type: 'error',
    })
    return Promise.reject(error)
  },
)
export default request
